package com.aaron.messenger.data;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;

import org.xmlpull.v1.XmlSerializer;

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Xml;

import com.aaron.messenger.data.DataManager.MessageDispatcher;
import com.aaron.messenger.net.NetPort;
import com.aaron.messenger.net.UdpReceiver;
import com.aaron.messenger.net.UdpSender;
import com.aaron.messenger.net.UdpReceiver.ChatDataReceivedListener;
import com.aaron.messenger.util.Utils;

class ChatManager implements ChatDataReceivedListener {
	
	private static final String TAG = "ChatManager";
	
	private ArrayList<ChatSession> mChatSessions = new ArrayList<ChatSession>();
	private XmlSerializer mSerializer = Xml.newSerializer();
	private long mId = System.currentTimeMillis();
	
	private UdpReceiver mReceiver;
	private Handler mCallbackHandler;
	
	private static ChatManager sInstance;
	
	private ChatManager(Handler handler) {
		mCallbackHandler = handler;
		startUdpReceiver();
	}
	
	public synchronized static ChatManager getInstance(Handler handler) {
		if(sInstance == null) {
			sInstance = new ChatManager(handler);
		}
		return sInstance;
	}
	
	@Override
	public void OnChatDataReceived(ChatMessage msg) {
		ChatSession session = getSession(msg.getSource());
		if(session == null) {
			session = new ChatSession();
			session.target = msg.getSource();
			mChatSessions.add(session);
		} 
		
		session.pendingmsg = true;
		session.chatcache.add(msg);
		if(mCallbackHandler != null) {
			Message message = mCallbackHandler.obtainMessage(MessageDispatcher.MSG_RECEIVE_DATA, msg);
			message.sendToTarget();
		}
	}
	
	public ChatSession getSession(String src) {
		for(ChatSession session:mChatSessions) {
			if(session.target.equals(src)) {
				return session;
			}
		}
		return null;
	}
	
	public ChatSession getSession(int index) {
		return mChatSessions.get(index);
	}
	
	public ArrayList<ChatSession> getChatSessions() {
		return mChatSessions;
	}
	
	public void removeSession(String target) {
		mChatSessions.remove(getSession(target));
	}
	
	public void setChatCallback(Handler handler) {
		mCallbackHandler = handler;
	}
	
	public void startUdpReceiver() {
		if(mReceiver == null) {
			mReceiver = new UdpReceiver("UdpReceiver");
			mReceiver.setChatListener(this);
			mReceiver.start();
		}
	}
	
	public void stopUdpReceiver() {
		if(mReceiver != null) {
			mReceiver.stopReceive();
			mReceiver = null;
		}
	}
	
	public void exit() {
		stopUdpReceiver();
		mCallbackHandler = null;
		sInstance = null;
	}
	
	 /**
	 * <message>
	 * <cmd>chat</cmd>
	 * <from>*.*.*.*</from>
	 * <to>*.*.*.*</to>
	 * <id>*</id>
	 * <packetnum>*</packetnum>
	 * <subid>*</subid>
	 * <data>***</data>
	 * <img>***</img>
	 * </message>
	 * 
	 * @throws IOException 
	 * @throws IllegalStateException 
	 * @throws IllegalArgumentException 
	 */
	public void chat(ArrayList<String> info, byte metadata, String target) throws IllegalArgumentException, IllegalStateException, IOException {
		ChatSession session = getSession(target);
		if(session == null) {
			session = new ChatSession();
			session.target = target;
			mChatSessions.add(session);
		} 
		ChatMessage msg = new ChatMessage();
		msg.data = info;
		msg.src = "127.0.0.1";
		msg.target = target;
		session.chatcache.add(msg);
		
		StringWriter writer = new StringWriter();
		mSerializer.setOutput(writer);
		
		mSerializer.startDocument("utf-8", true);
		mSerializer.startTag(null, "message");
		mSerializer.startTag(null, "cmd");
		mSerializer.text("chat");
		mSerializer.endTag(null, "cmd");
		mSerializer.startTag(null, "from");
		mSerializer.text(Utils.peekLocalIp());
		mSerializer.endTag(null, "from");
		mSerializer.startTag(null, "to");
		mSerializer.text(target);
		mSerializer.endTag(null, "to");
		mSerializer.startTag(null, "id");
		mSerializer.text(String.valueOf(mId));
		mSerializer.endTag(null, "id");
		mSerializer.startTag(null, "packetnum");
		mSerializer.text("1");
		mSerializer.endTag(null, "packetnum");
		mSerializer.startTag(null, "data");
		mSerializer.text(info.get(0));
		mSerializer.endTag(null, "data");
		mSerializer.endTag(null, "message");
		mSerializer.endDocument();
		
		UdpSender.sendUdp(writer.toString().getBytes("utf-8"), target, NetPort.UDP_CHAT_PORT);
		mId ++;
	}

}
